//
// Created by suzhen on 16-12-9.
//

#include "Orion.h"
#include "Coroutine.h"

USING_ORION_V2


//####################################Configuration######################################################

Configuration::Configuration(const std::string &bindAddr_,
                             uint bindPort_,
                             size_t maxBackLog_,
                             bool allowReuseAddr_,
                             uint socketIdleMs_)
        : bindAddr(bindAddr_),
          bindPort(bindPort_),
          maxBackLog(maxBackLog_),
          allowReuseAddr(allowReuseAddr_ ? 1 : 0 /* :D */),
          socketIdleMs(socketIdleMs_) {
}

//###################################Configuration#######################################################

//########################################TlsConf##################################################
TlsConf::TlsConf() : isValid_(NO) {
}

TlsConf::TlsConf(const std::string &certFilePath,
                 const std::string &keyFilePath)
        : isValid_(NO),
          passByUser_(NO),
          certFilePath_(certFilePath),
          keyFilePath_(keyFilePath) {
    sslCtxContext_ = SSL_CTX_new(SSLv23_server_method());
    CHECK(sslCtxContext_) << "SSL_CTX_new 失败!";
    SSL_CTX_set_options (sslCtxContext_, SSL_OP_NO_SSLv3);
    CHECK(sslCtxContext_) << "错误,无法加载SSL组件";
    CHECK(SSL_CTX_use_certificate_file(sslCtxContext_, certFilePath_.c_str(), SSL_FILETYPE_PEM))
    << "无法读取 ssl cert 文件,或者cert文件有误";
    CHECK(SSL_CTX_use_PrivateKey_file(sslCtxContext_, keyFilePath_.c_str(), SSL_FILETYPE_PEM))
    << "无法读取 ssl key 文件,或者key文件有误";
    CHECK(SSL_CTX_check_private_key(sslCtxContext_))
    << "ssl 证书与密钥不匹配";
    isValid_ = YES;
}

TlsConf::TlsConf(SSL_CTX *usrCtx)
        : isValid_(usrCtx != NULL),
          passByUser_(YES),
          sslCtxContext_(usrCtx) {}

TlsConf::~TlsConf() {
    if (sslCtxContext_
        && isValid_
        && !passByUser_) {
        SSL_CTX_free(sslCtxContext_);
    }
}

SSL_CTX *TlsConf::getNativeSslCtx() {
    return sslCtxContext_;
}

bool TlsConf::isSslCtxValid() const {
    return isValid_;
}

const std::string &TlsConf::getCertFilePath() {
    return certFilePath_;
}

const std::string &TlsConf::getKeyFilePath() {
    return keyFilePath_;
}

TlsConf &TlsConf::operator=(TlsConf &&other) {
    if (this == &other) {
        return *this;
    }
    isValid_ = other.isValid_;
    passByUser_ = other.passByUser_;
    certFilePath_ = std::move(other.certFilePath_);
    keyFilePath_ = std::move(other.keyFilePath_);
    sslCtxContext_ = other.sslCtxContext_;
    other.isValid_ = NO;
    other.sslCtxContext_ = NULL;
    return *this;
}

TlsConf::TlsConf(TlsConf &&other)
        : isValid_(other.isValid_),
          passByUser_(other.passByUser_),
          certFilePath_(std::move(other.certFilePath_)),
          keyFilePath_(std::move(other.keyFilePath_)),
          sslCtxContext_(other.sslCtxContext_) {
    other.isValid_ = NO;
    other.sslCtxContext_ = NULL;
}
//########################################TlsConf##################################################

void Orion::V2::OrionInit() {
    Coroutine::InitCoroutine();
}

